﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace GameBase
{
    public enum ORIGIN_POSITION
    {
        Center, TopLeft, TopRight, BottomLeft, BottomRight, MidLeft, MidRight, MidTop, MidBottom
    }

    public class Sprite
    {
        protected Texture2D texture;
        protected int row;
        protected int col;
        protected int width;
        protected int height;
        protected int delay;

        protected Vector2 origin;
        protected SpriteEffects effect = SpriteEffects.None;
        protected Color color = Color.White;
        protected float anpha = 1;
        //protected Vector2 position;
        private long currentTotalTime;

        protected List<int> frameSequence;
        protected int currentFrame = 0;

        private float rotate;

        private bool isOverOneTime = false;
        private bool isVisible = true;

        private bool isPlayOneTime = false;

        public bool IsPlayOneTime
        {
            get { return isPlayOneTime; }
            set { isPlayOneTime = value; }
        }

        public Texture2D Texture
        {
            get { return texture; }
            set { texture = value; }
        }

        public float Rotate
        {
            get { return rotate; }
            set { rotate = value; }
        }

        public float Anpha
        {
            get { return anpha; }
            set { anpha = value; }
        }

        public int Delay
        {
            get { return delay; }
            set { delay = value; }
        }
        public List<int> FrameSequence
        {
            get { return frameSequence; }
            set { 
                frameSequence = value;
                currentFrame = 0;
            }
        }

        public SpriteEffects Effect
        {
            get { return effect; }
            set { effect = value; }
        }
        public Vector2 Origin
        {
            get { return origin; }
            set { origin = value; }
        }
        public int Width
        {
            get { return width; }
        }
        public int Height
        {
            get { return height; }
        }
        public int CurrentFrame
        {
            get { return currentFrame; }
            set { currentFrame = value; }
        }
        public Color Color
        {
            get { return color; }
            set { color = value; }
        }

        public Sprite(string strFilePath, int row, int col)
        {
            List<int> frameSequence = new List<int>();
            int n = row * col;
            for (int i = 0; i < n; i++)
                frameSequence.Add(i);
            Init(strFilePath, row, col, frameSequence, 40);
        }
        public Sprite(Texture2D texture, int row, int col)
        {
            List<int> frameSequence = new List<int>();
            int n = row * col;
            for (int i = 0; i < n; i++)
                frameSequence.Add(i);
            Init(texture, row, col, frameSequence, 40);
        }   
        public Sprite(string strFilePath, int row, int col, List<int> frameSequence, int delay)
        {
            Init(strFilePath, row, col, frameSequence, delay);
        }

        public Sprite(Texture2D texture, int row, int col, List<int> frameSequence, int delay)
        {
            Init(texture, row, col, frameSequence, delay);
        }

        private void Init(string strFilePath, int row, int col, List<int> frameSequence, int delay)
        {
            Init(Constant.content.Load<Texture2D>(strFilePath), row, col, frameSequence, delay);
        }
        private void Init(Texture2D texture, int row, int col, List<int> frameSequence, int delay)
        {
            this.texture = texture;

            this.row = row;
            this.col = col;
            width = texture.Width / col;
            height = texture.Height / row;
            this.frameSequence = frameSequence;
            this.Delay = delay;
            origin = Vector2.Zero;
        }
        public void SetOriginPosition(Vector2 originz)
        {
            origin = originz;
        }
        public void SetOriginPosition(ORIGIN_POSITION originPos)
        {
            switch (originPos)
            {
                case ORIGIN_POSITION.Center:
                    origin = new Vector2(width / 2, height / 2);
                    break;
                case ORIGIN_POSITION.TopLeft:
                    origin = Vector2.Zero;
                    break;
                case ORIGIN_POSITION.TopRight:
                    origin = new Vector2(width, 0);
                    break;
                case ORIGIN_POSITION.BottomLeft:
                    origin = new Vector2(0, height);
                    break;
                case ORIGIN_POSITION.BottomRight:
                    origin = new Vector2(width, height);
                    break;
                case ORIGIN_POSITION.MidLeft:
                    origin = new Vector2(0, height / 2);
                    break;
                case ORIGIN_POSITION.MidRight:
                    origin = new Vector2(width, height / 2);
                    break;
                case ORIGIN_POSITION.MidTop:
                    origin = new Vector2(width / 2, 0);
                    break;
                case ORIGIN_POSITION.MidBottom:
                    origin = new Vector2(width / 2, height);
                    break;
            }
        }
        public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            Draw(gameTime, spriteBatch, 1);
        }
        
        public void Draw(GameTime gameTime, SpriteBatch spriteBatch, float depth)
        {
            Draw(gameTime, spriteBatch, Vector2.Zero, rotate,1, depth);
        }
        public void Draw(GameTime gameTime, SpriteBatch spriteBatch,
            Vector2 position, Vector2 scale, float depth)
        {
            if (!isVisible)
                return;
            int frame = CurrentFrame;
            if (FrameSequence != null && FrameSequence.Count > 0)
            {
                frame = FrameSequence[CurrentFrame];
            }
            spriteBatch.Draw(texture,
                position,
                new Rectangle((frame % col) * Width, (frame / col) * Height, Width, Height),
                color * anpha,
                rotate,
                origin,
                scale,
                effect,
                depth);
                
        }
        public void Draw(GameTime gameTime, SpriteBatch spriteBatch,
            Vector2 position,float rotatez,float scale,float depth)
        {
            if (!isVisible)
                return;
            int frame = CurrentFrame;
            if (FrameSequence != null && FrameSequence.Count > 0)
            {
                frame = FrameSequence[CurrentFrame];
            }
            spriteBatch.Draw(texture,
                position,
                new Rectangle((frame % col) * Width, (frame / col) * Height, Width, Height),
                color * anpha,
                rotatez+rotate,
                origin,
                scale,
                effect,
                depth);
        }
        public void Update(GameTime gameTime)
        {
            if (isPlayOneTime && isOverOneTime)
            {
                isVisible = false;
                return;
            }

            currentTotalTime += gameTime.ElapsedGameTime.Milliseconds;
            if (FrameSequence == null || FrameSequence.Count == 0)
                return;
            if (currentTotalTime >= Delay)
            {
                currentTotalTime = 0;
                CurrentFrame = (CurrentFrame + 1) % FrameSequence.Count;

                if (CurrentFrame == 0)
                    isOverOneTime = true;
            }
        }

        public Rectangle GetBound(Vector2 translate,float scale)
        {
            return new Rectangle((int)(translate.X - origin.X * scale),
                (int)(translate.Y - origin.Y * scale),
                (int)(Width*scale), (int)(Height*scale));
        }
        /*public Rectangle GetBound(float scale,Vector2 translate)
        {
            return new Rectangle((int)(translate.X - origin.X),
                (int)(translate.Y - origin.Y),
                (int)(Width * scale), (int)(Height * scale));
        }*/
        public Rectangle GetBound(Vector2 translate, Vector2 scale)
        {
            return new Rectangle((int)(translate.X - origin.X),
                (int)(translate.Y - origin.Y),
                (int)(Width * scale.X), (int)(Height * scale.Y));
        }
        static public List<int> String2Sequence(string strSequence)
        {
            strSequence = strSequence.Trim();
            if(strSequence == null || strSequence.Length == 0)
			{
				return null;
            }
			String[] strs = strSequence.Split(' ');
			if(strs.Length == 0)
			{
				return null;
			}
			
            List<int> sequence = new List<int>();
				
				foreach(string clause in strs)
				{
					try
					{		
						String[] mult = clause.Split('x');
						int loop=1;
						
						if(mult.Length == 0)
						{
							continue;
						}
						if(mult.Length == 2)
						{
							loop = int.Parse(mult[1]);
						}
						string str = mult[0];
						for(int i=0;i<loop;i++)
						{
							string[] series = str.Split('-');
							if(series.Length == 2)
							{
                                int start = int.Parse(series[0]);
                                int end = int.Parse(series[1]);
								if(start < end)
								{
									for(int k= start;k<=end;k++)
									{
										sequence.Add(k);
									}
								}
								else 
								{
									for(int k= start;k>=end;k--)
									{
										sequence.Add(k);
									}
								}
							}
							else if(series.Length == 1)
							{
                                sequence.Add(int.Parse(str));
							}
						}
					}
					catch
					{
                        return null;
					}
				}
                return sequence;
        }
    }
}
